package com.dyh.quickdemo.demos.UnsafeFunc;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

import java.util.function.Function;
import java.util.function.Supplier;

/*
@Author=Joey Wheeler
@Date=2020/10/27 15:26
抄的 doug lea 冚家铲
*/
@Slf4j
public class TestNextCmd {

     volatile Object next;
     long $next;//地址
     volatile Object result;
     long $result;//地址

    Supplier supplier;

    public TestNextCmd( Supplier supplier){
        this.supplier = supplier;
    }

    {
        try {
            $next = UnsafeHelper.getUnsafe().objectFieldOffset(TestNextCmd.class.getDeclaredField("next"));
            $result = UnsafeHelper.getUnsafe().objectFieldOffset(TestNextCmd.class.getDeclaredField("result"));
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }


    public TestNextCmd then(Supplier supplier){
        TestNextCmd n  = new  TestNextCmd(supplier);
        UnsafeHelper.getUnsafe().putOrderedObject(this, $next,n);
        return n;
    }
    public TestNextCmd then(){
        return (TestNextCmd) next;
    }

    public void start(){
//        Object that = this;
        /*CAS 不阻塞 CPU自旋*/
        UnsafeHelper.getUnsafe().compareAndSwapObject(this,$result,null,this.supplier.get());
        log.info("result={}",result);
        if (next!=null){
            ((TestNextCmd)next).start();
        }

//        for (;;){
//            UnsafeHelper.getUnsafe().compareAndSwapObject(this,$result,null,this.supplier.get());
//            log.info("result=",result);
//            if (next!=null)
//                ((TestNextCmd)next).start();
//            else
//                break;
//        }

    }

//    public  void next(Object o2){
//        /*instance*/
//        UnsafeHelper.getUnsafe().putOrderedObject(this, $next,o2);
//    }

    public static void main(String[] args) {
        TestNextCmd init = new  TestNextCmd(()->"1");

        init.then(()->{
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "2";
        }).then(()->"3");

        init.start();
    }

//    @Test
//    public void test(){
//
//
//
//    }
    /*
    @Test
    public void test(){
        System.out.println("test");
        Runnable r1 = ()->{
            System.out.println("r1");
        };
        Runnable r2 = ()->{
            System.out.println("r2");
        };
       // TestNextCmd cmd = new TestNextCmd().next(supplier);
        cmd.next(r1);
        System.out.println();
        ((Runnable)cmd.next).run();


//        TestNextCmd nextCmd = new TestNextCmd();
        //UnsafeHelper.getUnsafe().putOrderedObject(r1, finalAddr,r2);

        System.out.println();
        //((Runnable)orderBarrier).run();
//        new Thread(
//                ()->{
//                    UnsafeHelper.getUnsafe().putOrderedObject(r1, finalAddr,r2);
//                    UnsafeHelper.getUnsafe().putOrderedObject(r2, finalAddr,null);
//                }
//        ).start();
//
//        while (orderBarrier!=null){
//            ((Runnable)orderBarrier).run();
//        }

    }

//    @Setter@Getter@AllArgsConstructor
//    class FuncChain{
//        Function f;
//        Function n;
//    }
//
//    public Object exe(FuncChain funcChain){
//        long addr = 0;
//        try {
//            addr = UnsafeHelper.getUnsafe().objectFieldOffset(FuncChain.class.getDeclaredField("result"));
//        } catch (NoSuchFieldException e) {
//            e.printStackTrace();
//        }
//
//        UnsafeHelper.getUnsafe().putOrderedObject(funcChain.f,addr,funcChain.n);
//    }
*/
}
